ARM development

Contents|Previous|Next
ARM development

The GNUPro Toolkit from Cygnus is a complete solution for C and C++ development for the ARM7/7T processor using both the 32-bit ARM instruction-set and the 16-bit THUMB instruction-set extensions. The tools include the compiler, interactive debugger, utilities and libraries. Debugger and linker support is also included for the PID Series Evaluation board.

The following documentation discusses cross-development with the ARM processors.

- GNUPro Toolkit features for ARM targets
- Compiler issues for ARM targets
- ABI summary for ARM targets
- The stack frame for ARM targets
- Assembler issues for ARM targets
- Linker issues for ARM targets
- Debugger issues for ARM targets
- Simulator issues for ARM
- Reducing code size on the ARM 7/7T

### GNUPro Toolkit features for ARM targets

The following documentation describes ARM7-specific features of the GNUPro Toolkit.

- Supported targets
- Object file formats
- Case sensitivity issues
- Supported tools
- Connecting t o the ARM7 PID (process ID) board

ARM7 and ARM7T processors are the supported hosts.
The following targets are supported for ARM targets.

- GNUPro Instruction Set Simulator
- PID Series Evaluation board

Both big-endian and little-endian mode may be selected. The default is little endian.
The following table shows the hosts supported by ARM targets.

CPU | Operating system | Vendor
(SPARC) | SunOS 4.1.4 | Sun
(SPARC) | Solaris 2.4-2.5.1 | Sun
(`x`86) | Windows 95 | Microsoft
(`x`86) | Windows NT | Microsoft

The ARM7 tools support the COFF and ELF object file formats. See Chapter 4, System V Application Binary Interface (Prentice Hall, 1990). Use `ld` (see Using `ld` in GNUPro Utilities) or `objcopy` (see Using `binutils` in GNUPro Utilities) to produce S-records.
For the Windows 95/NT toolchain the libraries are installed in different locations. Therefore, the Windows 95/NT hosted toolchain requires environmental settings to function properly, as designated in the following example’s declaration (the variable, <`yymmdd`>, indicates the release date found on the CD).

    SET PROOT=C:\cygnus\arm-<yymmdd>

    SET PATH=%PROOT%\H-i386-cygwin32\BIN;%PATH%

    SET INFOPATH=%PROOT%\info

    REM Set TMPDIR to point to a ramdisk if you have one

    SET TMPDIR=%PROOT%

The following strings are case sensitive under UNIX and Windows NT.

- Command line options
- Assembler labels
- Linker script commands
- Section names

The following strings are not case sensitive under UNIX or Windows NT:

- GDB commands
- Assembler instructions and register names

File names are case sensitive under UNIX. Case sensitivity for Windows NT is dependent on system configuration. By default, file names under Windows NT are not case sensitive.
Cross-development tools in the Cygnus GNUPro Toolkit normally have names that reflect the target processor and the object file format output by the tools (ELF or COFF). This makes it possible to install more than one set of tools in the same binary directory, including both native and cross-development tools.
The complete tool name is a three-part hyphenated string. The first part indicates either a 32-bit ARM tool (`arm`), or a 16-bit THUMB tool (`thumb`). The second part indicates the file format output by the tool (`elf` or `coff`). The third part is the generic tool name (`gcc`). For example, the GCC compiler for the ARM7 is either ‘`arm-elf-gcc`’ or ‘`arm-coff-gcc`’ and the GCC compiler for the ARM7T is either ‘`thumb-elf-gcc`’ or ‘`thumb-coff-gcc`’.
The ARM7/7T package includes the following supported tools.

Tool description | Tool name
|  | ARM | THUMB
| GCC compiler | `arm-coff-gcc` `arm-elf-gcc` | `thumb-coff-gcc` `thumb-elf-gcc`
| C++ compiler | `arm-coff-c++` `arm-elf-c++` | `thumb-coff-c++` `thumb-elf-c++`
| GNU assembler | `arm-coff-as` `arm-elf-as` | `thumb-coff-as` `thumb-elf-as`
| GNU LD linker | `arm-coff-ld` `arm-elf-ld` | `thumb-coff-ld` `thumb-elf-ld`
| Standalone simulator | `arm-coff-run` `arm-elf-run` | `thumb-coff-run` `thumb-elf-run`

Binary utilities

`arm-coff-ar`
`arm-elf-ar`
`arm-coff-nm`
`arm-elf-nm`
`arm-coff-objcopy`
`arm-elf-objcopy`
`arm-coff-objdump`
`arm-elf-objdump`
`arm-coff-ranlib`
`arm-elf-ranlib`
`arm-coff-size`
`arm-elf-size`
`arm-coff-strings`
`arm-elf-strings`
`arm-coff-strip`
`arm-elf-strip`

`thumb-coff-ar`
`thumb-elf-ar`
`thumb-coff-nm`
`thumb-elf-nm`
`thumb-coff-objcopy`
`thumb-elf-objcopy`
`thumb-coff-objdump`
`thumb-elf-objdump`
`thumb-coff-ranlib`
`thumb-elf-ranlib`
`thumb-coff-size`
`thumb-elf-size`
`thumb-coff-strings`
`thumb-elf-strings`
`thumb-coff-strip`
`thumb-elf-strip`

| GDB debugger | `arm-coff-gdb` `arm-coff-gdb` | `thumb-coff-gdb` `thumb-elf-gdb`

The binaries for a Windows NT hosted toolchain are installed with the `.exe` suffix. However, the `.exe` suffix does not need to be specified when running the executable.
The GNUPro Toolkit supports communication with the ARM7 PID board, using GDB to communicate with the Embedded ICE interface, which is connected to the ARM 7 PID board.
Connecting to the ARM7 PID target
Use the following instructions to connect the ARM7 PID (process ID) board. The ARM PID board gets its power from a PC AT power supply, using the P8 and P9 connectors. The Embedded ICE interface box requires a 9V DC 500 mA power supply with a center-positive connector, one of which should have been provided with the Embedded ICE board.
To establish a serial connection, use the following process.

1. Connect the serial port.

The Embedded ICE board needs to connect to the serial port of the host computer, which will be running GDB. A serial cable is supplied with the Embedded ICE. It has three connectors, the one labeled ARM connects to the Embedded ICE, the other two provide the option of connecting to either a Sun type (DB25) serial port or a PC type (DB 9) serial port, and they are labeled as such. Only one of these can be used at a time. Embedded ICE comes with a short ribbon cable, which has a 14-pin header connector on each end. One end connects to the port on the front of the Embedded ICE box. The other end connects to port PL1 on the ARM 7 processor daughtercard.

2. Test the serial connection.

Run GDB on the host computer. Type `target rdi <serial port>` where `<serial port>` is the name of the serial port to which the Embedded ICE connects. Examples are `/dev/ttya` on a UNIX system or `com1` on a PC. This should return a few lines of information about the version of the Embedded ICE. The following output is an example of the initialization.

    (gdb) target rdi /dev/com3

    EmbeddedICE Manager (ADP, ARM7TDI) 2.02 (Advanced RISC Machines SDT 2.10)

    Connected to ARM RDI target.

At this point, use GDB commands normally. If a GDB error message is returned, try resetting the Embedded ICE box by pressing the small red button on the front, then checking all power and cable connections as well as the host computer port configuration. For testing purposes, if you use a program to monitor the serial port to which the Embedded ICE is connected, you will see the version information that the Embedded ICE emits on the serial line every time it is powered up or reset.
Compiler issues for ARM and THUMB targets
The following documentation describes ARM7 and ARM7T-specific features of the GNUPro Compiler. For a list of available generic compiler options, see GNU CC command options in Using GNU CC in GNUPro Compiler Tools. In addition, the following documentation describes the ARM and THUMB specific command-line options that are supported.
ARM compiler options
The following options are specific to the `arm-coff-gcc` and `arm-elf-gcc` configurations.

`-mapcs-frame`

Generate a stack frame upon entry to a function, as defined in the ARM Procedure Calling Standard (APCS).

`-mno-apcs-frame`

Do not generate a stack frame upon entry to a function. The APCS (APCS) specifies that the generation of stack frames is optional, hence this pair of options. Not generating stack frames produces slightly smaller and faster code. Default setting.

`-mapcs-32`

Produce assembly code which conforms to the 32 bit version of the ARM Procedure Calling Standard. Default setting.

`-mapcs-26`

Produce assembly code which conforms to the 26 bit version of the ARM Procedure Calling Standard, as used by earlier versions of the ARM processor (ARM2, ARM3).

`-mapcs-stack-check`

Produce assembly code which checks the amount of stack space available upon entry to a function and which calls a suitable function if their is insufficient space available.

`-mno-apcs-stack-check`

Do not produce code to check for stack space upon entry to a function. Default setting.

`-mapcs-reentrant`

Produce assembly code that is position independent and reentrant.

`-mno-apcs-rentrant`

Do not produce position independent, reentrant assembly code. Default setting.

`-mshort-load-bytes`

Two byte values should be loaded by performing two individual byte loads and then merging the results. This allows shorts to be loaded from non-aligned addresses without generating a memory access fault.

`-mno-short-load-bytes`

Two byte values should be loaded using the most space efficient method. On an ARM processor that supports half word loads these instructions will be used. Default setting.

`-mfpe`

Floating point instructions should be emulated by the ARM Floating Point Emulator code, which is supplied by the operating system.

`-mfpe=N`

Floating point instructions should be emulated by the ARM Floating Point Emulator code version, `N`. Valid version numbers are 2 and 3.

2 is the default setting.

`-msoft-float`

Floating point instructions should be emulated by library calls. Default setting.

`-mhard-float`

Floating point instructions can be performed in hardware.

`-mbig-endian`

Produce assembly code which is targeted for a big endian processor.

`-mlittle-endian`

Produce assembly code which is targeted for a little endian processor. Default setting.

`-mwords-little-endian`

Produce assembly code which is targeted for a big endian processor, but which stores words in a little endian format. This is for backward compatibility with older versions of GCC.

`-mthumb-interwork`

Produce assembly code which supports calls between the ARM instruction set and the THUMB instruction set.

`-mno-thumb-interwork`

Do not produce code specifically intended to support calling between ARM and THUMB instruction sets. Default setting.

`-msched-prolog`

Allow instructions in function prologues to be rearranged to improve performance. Default setting.

`-mno-sched-prolog`

Do not allow the instructions in function prologues to be rearranged. This guarantees that function prologues will have a well-defined form, depending upon their nature.

`-mcpu=XXXX`

Produce assembly code specifically for the indicated processor. The ‘`XXXX`’ variable can be one of the following processors.

- `arm2`
- `arm250`
- `arm3`
- `arm6`
- `arm600`
- `arm610`
- `arm620`
- `arm7`
- `arm7m` (the default setting)
- `arm7d`
- `arm7dm`
- `arm7di`
- `arm7dmi`
- `arm70`
- `arm700`
- `arm700i`
- `arm710`
- `arm710c`
- `arm7100`
- `arm7500`
- `arm7500fe`
- `arm7tdmi`
- `arm8`
- `strongarm`
- `strongarm110`

`-march=XXXX`

Produce assembly code specifically for an ARM processor of the indicated architecture. The ‘`XXXX`’ variable can be one of the following architectures.

- `armv2`
- `armv2a`
- `armv3`
- `armv3m`
- `armv4` (the default setting)
- `armv4t`

THUMB options
The following options are specific to the `thumb-coff-gcc` and `thumb-elf-gcc` configurations.

`-mtpcs-frame`

Generate a stack frame upon entry to a non-leaf function, as defined in the THUMB Procedure Calling Standard (`tpcs`). A leaf function is one which does not call any other function.

`-mno-tpcs-frame`

Do not generate a stack frame upon entry to a non-leaf function. The THUMB Procedure Calling Standard (`tpcs`) specifies that the generation of stack frames is optional, hence this pair of options. Default setting.

`-mtpcs-leaf-frame`

Generate a stack frame upon entry to a leaf function, as defined in the THUMB Procedure Calling Standard (`tpcs`).

`-mno-tpcs-leaf-frame`

Do not generate a stack frame upon entry to a leaf function, as defined in the THUMB Procedure Calling Standard (`tpcs`). Default setting.

`-mbig-endian`

Produce assembly code which is targeted for a big endian processor.

`-mlittle-endian`

Produce assembly code which is targeted for a little endian processor. Default setting.

`-mthumb-interwork`

Produce assembly code which supports calls between the ARM instruction set and the THUMB instruction set.

`-mno-thumb-interwork`

Do not produce code specifically intended to support calling between ARM and THUMB instruction sets. If such calls are used, they will probably fail. This is the default setting.

Preprocessor symbols for ARM and THUMB targets
The following `arm-coff-gcc` and `arm-elf-gcc` specific preprocessor symbols are supported.

Symbol | Condition
`arm` | Always defined.
`__semi__` | Always defined.
`__APCS_32__` | If `-mapcs-26` has not been specified.
`__APCS_26__` | If `-mapcs-26` has been specified.
`__SOFTFP__` | If `-mhard-float` has not been specified.
`__ARMWEL__` | If `-mwords-little-endian` has been specified.
`__ARMEB__` | If `-mbig-endian` has been specified.
`__ARMEL__` | If `-mbig-endian` has not been specified.
`__arm2` | If `-mcpu=arm2` has been specified.
`__arm250` | If `-mcpu=arm250` has been specified.
`__arm3` | If `-mcpu=arm3` has been specified.
`__arm6` | If `-mcpu=arm6` has been specified.
`__arm60` | If `-mcpu=arm60` has been specified.
`__arm600` | If `-mcpu=arm600` has been specified.
`__arm610` | If `-mcpu=arm610` has been specified.
`__arm620` | If `-mcpu=arm620` has been specified.
`__arm7` | If `-mcpu=arm7` has been specified.
`__arm7m` | If `-mcpu=arm7m` has been specified.
`__arm7d` | If `-mcpu=arm7d` has been specified.
`__arm7dm` | If `-mcpu=arm7dm` has been specified.
`__arm7di` | If `-mcpu=arm7di` has been specified.
`__arm7dmi` | If `-mcpu=arm7dmi` has been specified.
`__arm70` | If `-mcpu=arm70` has been specified.
`__arm700` | If `-mcpu=arm700` has been specified.
`__arm700i` | If `-mcpu=arm700i` has been specified.
`__arm710` | If `-mcpu=arm710` has been specified.
`__arm710c` | If `-mcpu=arm710c` has been specified.
`__arm7100` | If `-mcpu=arm7100` has been specified.
`__arm7500` | If `-mcpu=arm7500` has been specified.
`__arm7500fe` | If `-mcpu=arm7500fe` has been specified.
`__arm7tdmi` | If `-mcpu=arm7tdmi` has been specified.
`__arm8` | If `-mcpu=arm8` has been specified.
`__strongarm` | If `-mcpu=strongarm` has been specified.
`__strongarm110` | If `-mcpu=strongarm110` has been specified.

The following `thumb-coff-gcc` and `thumb-elf-gcc` specific preprocessor symbols are supported.

Symbol | Condition
`THUMB` | Always defined.
`__THUMB` | Always defined.
`__ARMEB__` | If `-mbig-endian` has been specified.
`__ARMEL__` | If `-mbig-endian` has not been specified.
`__THUMBEB__` | If `-mbig-endian` has been specified.
`__THUMBEL__` | If `-mbig-endian` has not been specified.

ARM7/7T-specific attributes

There are no ARM7/7T-specific attributes. See Declaring attributes of functions and Specifying attributes of variables in Extensions to the C language family in Using GNU CC in GNUPro Compiler Tools for more information.
ABI summary for ARM targets
The ARM7 tools adhere by default to the APCS (ARM Procedure Call Standard). The ARM7T tools adhere to the TPCS (THUMB Procedure Call Standard). The following documentation of the ABI is consistent with both these standards.

- Data types sizes and alignments for ARM targets
- Subroutine calls for ARM targets
- The stack frame for ARM targets
- C language calling conventions for ARM targets
- Function return values for ARM targets

Data types sizes and alignments for ARM targets
The following table shows the size and alignment for all data types.
Data types and size alignment for ARM targets

Type | Size (bytes) | Alignment (bytes)
`char` | 1 byte | 1 byte
`short` | 2 bytes | 2 bytes
`int` | 4 bytes | 4 bytes
`unsigned` | 4 bytes | 4 bytes
`long` | 4 bytes | 4 bytes
`long long` | 8 bytes | 8 bytes
`float` | 4 bytes | 4 bytes
`double` | 8 bytes | 8 bytes
pointer | 4 bytes | 4 bytes

The following information is necessary for specifying data type sizes and alignment for ARM targets.

- Alignment within aggregates (structs and unions) is as above, with padding added if needed
- Aggregates have alignment equal to that of their most aligned member
- Aggregates have sizes which are a multiple of their alignment

#### Subroutine calls for ARM targets

The following lists describe the calling conventions for subroutine calls.

Parameter registers
General-purpose | `r0-r3`

Register usage
volatile | `r0` through `r3` , `r12`
non-volatile | `r4` through `r10`
frame pointer | `r11`
stack pointer | `r13`
return address | `r14`
program counter | `r15`

Note:
Structures that are less than or equal to 32 bits in length are passed as values.
Structures that are greater than 32 bits in length are passed as pointers.

### The stack frame for ARM targets

The following documentation describes ARM stack frames.

- The stack grows downwards from high addresses to low addresses.
- A leaf function need not allocate a stack frame if it does not need one.
- A frame pointer need not be allocated.
- The stack pointer shall always be aligned to 4 byte boundaries.
- The stack pointer always points to the lowest addressed word currently stored on the stack.

See ARM stack frames for functions that take a fixed number of arguments for an illustartion of how stack frames for functions appear that take a fixed number of arguments.

###### ARM stack frames for functions that take a fixed number of arguments

See ARM stack frames for functions that take a variable number of arguments for an illustration of how stack frames appear for functions that take a variable number of arguments.

###### ARM stack frames for functions that take a variable number of arguments

#### C language calling conventions for ARM targets

A floating-point value occupies one, two, or three words, as appropriate to its type. Floating point values are encoded in IEEE 754 format, with the most significant word of a double having the lowest address.
Note:
When targetting little-endian ARMs, the words that make up a double will be stored in big-endian order, while the bytes inside each word will be stored in little-endian order..
The C compiler widens arguments of type float to type double to support inter-working between ANSI C and classic C.
Char, short, pointer and other integral values occupy one word in an argument list. Character and short values are widened by the C compiler during argument marshalling.
A structure always occupies an integral number of words (unless this is overridden by the `-mstructure-size-boundry` command line option).
Argument values are collated in the order written in the source program The first four words of the argument values are loaded into `r0` through `r3`', and the remainder are pushed on to the stack in reverse order (so that arguments later in the argument list have higher addresses than those earlier in the argument list). As a consequence, a FP value can be passed in integer registers, or even split between an integer register and the stack.

#### Function return values for ARM targets

The following documentation describes how different data types are returned.
Floats and integer-like values are returned in register `r0` '.
A type is integer-like if its size is less than or equal to one word and if the type is a structure, union or array, then all of its addressable sub-fields must have an offset of zero. For example, the following example's declaration is integer-like in form.

    struct {int a:8, b:8, c:8, d:8;}

The following example's declaration is similar.

    union {int i; char*p;}

However, the following declaration is unlike the previous example declarations since it is possible to take the address of fields B, C or D, and their offsets from the start of the structure are not zero.

    struct {char A; char B; char c; char D;}

Doubles and `long long` integers are returned in registers `r0` and `r1`. For doubles `r0` always contains the most significant word of the double. For `long long` ' values `r0`only contains the most significant word if the target is
big-endian. All other values are returned by placing them into a suitably sized area of memory provided for this purpose by the function's caller. A pointer to this area of memory is passed to the function as a hidden first argument, generated at compile time like the following example’s declaration.

    LargeType t;

    t = func(arg);

The previous declaration is implemented in a manner similarly to the following example’s declaration.

    LargeType t;

    (void) func(&t,arg);

### Assembler issues for ARM targets

The following documentation describes ARM7/7T-specific features of the GNUPro assembler.
The ARM7/7T syntax is based on the syntax in ARM’s ARM7 Architecture Manual.
For a list of available generic assembler options, see Command-line options in Using `as` in GNUPro Utilities. The following are ARM7/7T specific assembler command-line options.
`-m[arm][1|2|250|3|6|7[t][d][m][i]]`

Select processor variant.

`-m[arm]v[2|2a|3|3m|4|4t]`

Select architecture variant.

`-mthumb`

Only allow THUMB instructions.

`-mall`

Allow any instruction.

`-mfpa10`

Select the v1.0 floating point architecture.

`-mfpa11`

Select the v1.1 floating point architecture.

`-mfpe-old`

Don’t allow floating-point multiple instructions.

`-mno-fpu`

Don’t allow any floating-point instructions.

`-mthumb-interwork`

Mark the assembled code as supporting inter-working.

`-mapcs-32`

Mark the code as supporting the 26 bit variant of the ARM Procedure calling standard. This is the default.

`-mapcs-26`

Mark the code as supporting the 26 bit variant of the ARM Procedure calling standard.

`-EB`

Assemble code for a big endian CPU.

`-EL`

Assemble code for a little endian CPU. This is the default.

Assembler comments start with the `@` (‘at’ symbol) and extend to the end of the line.

### Register names for the ARM7/7T targets

The following lists the register names supported for the ARM7/7T, using the ‘register name, register number’ format.

General registers
`r0`: 0 | `r1`: 1 | `r2`: 2 | `r3`: 3
`r4`: 4 | `r5`: 5 | `r6`: 6 | `r7`: 7
`r8`: 8 | `r9`: 9 | `r10`: 10 | `r11`: 11
`r12`: 12 | `r13`: 13 | `r14`: 14 | `r15`: 15

APCS names for the general registers
`a1`: 0 | `a2`: 1 | `a3`: 2 | `a4`: 3
`v1`: 4 | `v2`: 5 | `v3`: 6 | `v4`: 7
`v5`: 8 | `v6`: 9 | `sb`: 9 | `v7`: 10
`sl`, 10 | `fp`: 11 | `ip`: 12 | `sp`: 13
`lr`: 14 | `pc`: 15 |  |

Floating point registers
`f0`: 16 | `f1`: 17 | `f2`: 18 | `f3`: 19
`f4`: 20 | `f5`: 21 | `f6`: 22 | `f7`: 23
`c0`: 32 | `c1`: 33 | `c2`: 34 | `c3`: 35
`c4`: 36 | `c5`: 37 | `c6`: 38 | `c7`: 39
`c8`: 40 | `c9`: 41 | `c10`: 42 | `c11`: 43
`c12`: 44 | `c13`: 45 | `c14`: 46 | `c15`: 47
`cr0`: 32 | `cr1`: 33 | `cr2`: 34 | `cr3`: 35
`cr4`: 36 | `cr5`: 37 | `cr6`: 38 | `cr7`: 39
`cr8`: 40 | `cr9`: 41 | `cr10`: 42 | `cr11`: 43
`cr12`: 44 | `cr13`: 45 | `cr14`: 46 | `cr15`: 47

#### Floating point support for ARM targets

The assembler supports hardware floating point, but the compiler does not.

#### Opcodes for ARM targets

For detailed information on the ARM7/7T machine instruction set, see ARM7 Series Instruction Manual. The GNU Assembler (GAS) implements all the standard opcodes.

#### Synthetic Instructions for ARM targets

Synthesized instructions are pseudo instructions that correspond to two or more actual machine instructions. The GNU assembler supports the following synthesized instructions.

> `.arm`

The following code uses the ARM instruction set.

> `.thumb`

The following code uses the THUMB instruction set.

> `.code 16`

An alias for `.thumb`

> `.code 32`

An alias for `.arm`

> `.force_thumb`

The following code uses the THUMB instruction set, and should be assembled even if the target processor does not support THUMB instructions.

> `.thumb_func`

The following label is the name of function which has been encoded using THUMB instructions, rather than ARM instructions.

> `.ltorg`

Start a literal pool.

#### ARM7/7T-specific assembler error messages

> `Error: Unrecognized opcode`

This instruction is misspelled or there is a syntax error somewhere.

> `Warning: operand out of range`

An immediate value was specified that is too large for the instruction

### Linker issues for ARM targets

The following documentation describes ARM7/7T-specific features of the GNUPro linker. For a list of available generic linker options, see Linker scripts in Using `ld` in GNUPro Utilities.

#### Linker script for ARM targets

The GNU linker uses a linker script to determine how to process each section in an object file, and how to lay out the executable. The linker script is a declarative program consisting of a number of directives. For instance, the `ENTRY()`directive specifies the symbol in the executable that will be the executable's entry point. For a complete description of the linker script, see Linker scripts in Using `ld` in GNUPro Utilities.
For the ARM7/7T tools, there are two linker scripts, one to be used when compiling for the simulator and one to be used when compiling for the evaluation board.
The following script is the `sim.ld` linker script for the simulator for ARM targets using COFF object file format.

    # Linker script for ARM COFF.

    # Based on i386coff.sc by Ian Taylor <ian@cygnus.com>.

    test -z "$ENTRY" && ENTRY=_start

    if test -z "${DATA_ADDR}"; then

    if test "$LD_FLAG" = "N" || test "$LD_FLAG" = "n"; then

    DATA_ADDR=.

    fi

    fi

    cat <<EOF

    OUTPUT_FORMAT("${OUTPUT_FORMAT}","${BIG_OUTPUT_FORMAT}","${LITTLE_OUTPUT_FORMAT}")

    ${LIB_SEARCH_DIRS}

    ENTRY(${ENTRY})

    SECTIONS

    {

    /* We start at 0x8000 because gdb assumes it (see FRAME_CHAIN).

    This is an artifact of the ARM Demon monitor using the bottom 32k

    as workspace (shared with the FP instruction emulator if

    present): */

    .text ${RELOCATING+ 0x8000} : {

    *(.init)

    *(.text)

    *(.glue_7t)

    *(.glue_7)

    *(.rdata)

    ${CONSTRUCTING+ ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;

    LONG (-1); *(.ctors); *(.ctor); LONG (0); }

    ${CONSTRUCTING+ ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;

    LONG (-1); *(.dtors); *(.dtor); LONG (0); }

    *(.fini)

    ${RELOCATING+ etext = .;}

    }

    .data ${RELOCATING+${DATA_ADDR-0x40000 + (. & 0xfffc0fff)}} : {

    ${RELOCATING+ __data_start__ = . ;}

    *(.data)

    ${RELOCATING+ __data_end__ = . ;}

    ${RELOCATING+ edata = .;}

    ${RELOCATING+ _edata = .;}

    }

    .bss ${RELOCATING+ SIZEOF(.data) + ADDR(.data)} :

    {

    ${RELOCATING+ __bss_start__ = . ;}

    *(.bss)

    *(COMMON)

    ${RELOCATING+ __bss_end__ = . ;}

    }

    ${RELOCATING+ end = .;}

    ${RELOCATING+ _end = .;}

    ${RELOCATING+ __end__ = .;}

    .stab 0 ${RELOCATING+(NOLOAD)} :

    {

    [ .stab ]

    }

    .stabstr 0 ${RELOCATING+(NOLOAD)} :

    {

    [ .stabstr ]

    }

    }

    EOF

### Debugger issues for ARM targets

The following documentation describes ARM7/7T-specific features of the GNUPro debugger, GDB. There are two ways for GDB to talk to an ARM7/7T target. Each target requires that the program be compiled with a target specific linker script.

- Simulator
GDB's built-in software simulation of the ARM7 processor allows the debugging of programs compiled for the ARM7/7T without requiring any access to actual hardware. For this target the linker script `sim.ld`must be specified at compilation. To activate this mode in GDB, type `target sim` and then load the code into the simulator by typing `load` and debug it in the normal fashion.
- Remote target board
For this target the linker script `eval.ld` must be specified at compilation. To connect to the target board in GDB, using the
`target remote` <`devicename`> command, where <`devicename`> will be a serial device such as `/dev/ttya` (UNIX) or `com2` (Windows NT). Then load the code onto the target board by typing the `load` command. After being downloaded, the program can be executed.

Note:
When using the remote target, GDB does not accept the `run` command. However, since downloading the program has the side effect of setting the PC to the start address, you can start your program by typing the `continue` command.
For the available generic debugger options, see Debugging with GDB in GNUPro Debugging Tools. There are no ARM7/7T-specific debugger command-line options.

#### Simulator issues for ARM targets

The simulator supports the following registers.

Type | Registers
volatile | `d0`, `d1`, `a0`, `a1`
saved | `d2`, `d3`, `a2`, `a3`
special purpose | `sp`, `pc`, `ccr`, `mdr`, `lar`, `lir`

Memory is 256K bytes starting at location 0. The stack starts at the highest memory address and works downward. The heap starts at the lowest address after the text, data and bss.
There are no ARM7/7T-specific simulator command-line options.

### Reducing code size on the ARM 7/7T

The ARM7/7T processor supports two different instruction sets. It can run the standard ARM instruction set, where each instruction occupies 32 bits, and also the reduced size THUMB instruction set, where each instruction occupies 16 bits. THUMB instructions are more limited in what they can do compared to ARM instructions, but they can represent a considerable saving in the amount of space occupied by the instructions. It is possible to dynamically switch between the two instruction sets, thus gaining the advantages of both.
The GNUPro compilers are able to produce code for both the ARM and THUMB instruction sets, but only at a file level of granularity. Thus the programmer can choose whether individual functions should be encoded as either ARM or THUMB instructions, but they cannot specify that specific parts of a function should be ARM or THUMB. The other parts of the GNUPro tools (the assembler and linker and so on), all support mixing ARM and THUMB code at any level.
The GNUPro toolkit has two compilers, one of which produces ARM assembler, and the other produces THUMB assembler. If the programmer wants to use just one instruction set to compile their program then no special procedures need to be followed, other than selecting the correct compiler. If the programmer wants to use both instruction sets in their program, then they must separate the ARM and THUMB parts of their program into separate files and compile each individually, while also specifiying the `-mthumb-interwork` command line flag. When the assembled object files are linked together the linker will generate special code to switch between the two instruction sets whenever a call is made from an ARM function to a THUMB function or vice versa.

> 1. Create source code.

Create the following sample source code and save it as `arm_stuff.c` .

    extern int thumb_func (int);

    int main (void) { return 7 + thumb_func (7); }

Create the following sample source code and save it as `thumb_tuff.c` .

    int thumb_func (int arg) { return arg + 7; }

> 2. Compile and link from source code.

First compile the ARM sample code with the following declaration.

    arm-coff-gcc -g -c -O2 -mthumb-interwork arm_stuff.c

Then compile the THUMB sample code with the following declaration.

    THUMB-coff-gcc -g -c -O2 -mthumb-interwork THUMB_stuff.c

Then link with the following declaration.

    arm-coff-gcc arm_stuff.o thumb_stuff.o -o program

The use of the `-g` and `-O2` command line options are optional. They are used in the previous examples to make the output of the debugger easier to understand.

#### Run on the stand-alone Simulator for ARM 7/7T targets

The following script example shows how to set up the stand-alone simulator for the ARM7/7T targets.

    C:\> arm-coff-gdb program

    GNU gdb 4.16-armT-970630

    Copyright 1997 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.

    Type "show copying" to see the conditions. This version of GDB is supported for customers of Cygnus Solutions. Type "show warranty" for details. This GDB was configured as "--host=i686-pc-linux-gnu

    --target=arm-acorn-coff"...

    (gdb) target sim

    Connected to the simulator.

    (gdb) load

    Loading section .text, size 0x8e8 lma 0x8000

    Loading section .data, size 0x2fc lma 0x408e8

    Start address 0x8000

    Transfer rate: 24352 bits in <1 sec.

    (gdb) break main

    Breakpoint 1 at 0x8048: file arm_stuff.c, line 2.

    (gdb) break thumb_func

    Breakpoint 2 at 0x8060: file thumb_stuff.c, line 1.

    (gdb) run

    Starting program: /elmo/scratchme/nickc/work/released/arm/gcc/tests/program

    Breakpoint 1, 0x8048 in main () at arm_stuff.c:2

    2 int main (void) { return 7 + thumb_func (7); }

    (gdb) disassemble

    Dump of assembler code for function main:

    0x803c <main>: mov ip, sp

    0x8040 <main+4>: stmdb sp!, {fp, ip, lr, pc}

    0x8044 <main+8>: sub fp, ip, #4

    0x8048 <main+12>: bl 0x8124 <__gccmain>

    0x804c <main+16>: mov r0, #7

    0x8050 <main+20>: bl 0x88b0 <__thumb_func_from_arm>

    0x8054 <main+24>: add r0, r0, #7

    0x8058 <main+28>: ldmdb fp, {fp, sp, lr}

    0x805c <main+32>: bx lr

    End of assembler dump.

    (gdb) continue

    Continuing.

    Breakpoint 2, thumb_func (arg=7) at thumb_stuff.c:1

    1 int thumb_func (int arg) { return 7 + arg; }

    (gdb) disassemble

    Dump of assembler code for function thumb_func:

    0x8060 <thumb_func>: 3007 add r0, #7

    0x8062 <thumb_func+2>: 4770 bx lr

    End of assembler dump.

    (gdb) quit

    The program is running. Quit anyway (and kill it)? (y or n) y

Note:
The ARM `add` instruction at `<main+24>` occupies 4 bytes, whereas the THUMB `add` instruction at `<thumb_func>` occupies 2 bytes.

Top|Contents|Previous|Next